//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.vere.orm.db;

import com.vere.orm.model.ClassItem;
import com.vere.orm.model.Property;
import com.vere.orm.util.CDataType;
import com.vere.orm.util.Constants;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class Session {
    private DBHelper db = new DBHelper();
    private boolean beginTransaction;

    public Session() {
    }

    public boolean save(Object obj) {
        Class clazz = obj.getClass();
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            System.out.println(fields);
            ClassItem classItem = this.buildRealTableMeta(fields, className, tableName);
            Object[] returnObj = this.buildInsertSQL(classItem, obj);
            String sql = returnObj[0].toString();
            Object[] params = (Object[])returnObj[1];
            boolean var11;
            if (this.beginTransaction) {
                var11 = this.db.executeTransactionUpdate(sql, params);
                return var11;
            }

            var11 = this.db.executeUpdate(sql, params);
            return var11;
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return false;
    }

    public boolean update(Object obj) {
        Class clazz = obj.getClass();
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            ClassItem classItem = this.buildRealTableMeta(fields, className, tableName);
            Object[] returnObj = this.buildUpdateSQL(classItem, obj);
            String sql = returnObj[0].toString();
            Object[] params = (Object[])returnObj[1];
            boolean var11;
            if (this.beginTransaction) {
                var11 = this.db.executeTransactionUpdate(sql, params);
                return var11;
            }

            var11 = this.db.executeUpdate(sql, params);
            return var11;
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return false;
    }

    public boolean delete(Object obj) {
        Class clazz = obj.getClass();
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();

        boolean var11;
        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            ClassItem classItem = this.buildRealTableMeta(fields, className, tableName);
            Object[] returnObj = this.buildDeleteSQL(classItem, obj);
            String sql = returnObj[0].toString();
            Object[] params = (Object[])returnObj[1];
            if (this.beginTransaction) {
                var11 = this.db.executeTransactionUpdate(sql, params);
                return var11;
            }

            var11 = this.db.executeUpdate(sql, params);
        } catch (Exception var14) {
            var14.printStackTrace();
            return false;
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return var11;
    }

    public Object findOne(Class clazz, String sql) {
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();
        Object obj = null;

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            System.out.println(fields);
            this.buildRealTableMeta(fields, className, tableName);
            List<Property> fieldNameList = this.getFieldNameList(className, sql);
            ResultSet rs = null;
            if (this.beginTransaction) {
                rs = this.db.executeTransactionQuery(sql);
            } else {
                rs = this.db.executeQuery(sql);
            }

            if (rs.next()) {
                obj = this.buildOneObject(clazz, fieldNameList, rs);
            }
        } catch (Exception var13) {
            var13.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return obj;
    }

    public Object findOne(Class clazz, String sql, Object[] params) {
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();
        Object obj = null;

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            System.out.println(fields);
            this.buildRealTableMeta(fields, className, tableName);
            List<Property> fieldNameList = this.getFieldNameList(className, sql);
            ResultSet rs = null;
            if (this.beginTransaction) {
                rs = this.db.executeTransactionQuery(sql, params);
            } else {
                rs = this.db.executeQuery(sql, params);
            }

            if (rs.next()) {
                obj = this.buildOneObject(clazz, fieldNameList, rs);
            }
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return obj;
    }

    public List find(Class clazz, String sql) {
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();
        List list = null;

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            this.buildRealTableMeta(fields, className, tableName);
            List<Property> fieldNameList = this.getFieldNameList(className, sql);
            ResultSet rs = null;
            if (this.beginTransaction) {
                rs = this.db.executeTransactionQuery(sql);
            } else {
                rs = this.db.executeQuery(sql);
            }

            list = this.buildList(clazz, fieldNameList, rs);
        } catch (Exception var13) {
            var13.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return list;
    }

    public List find(Class clazz, String sql, Object[] params) {
        String className = clazz.getName();
        String tableName = clazz.getSimpleName();
        List list = null;

        try {
            clazz = Class.forName(className);
            Field[] fields = clazz.getDeclaredFields();
            this.buildRealTableMeta(fields, className, tableName);
            List<Property> fieldNameList = this.getFieldNameList(className, sql);
            ResultSet rs = null;
            if (this.beginTransaction) {
                rs = this.db.executeTransactionQuery(sql, params);
            } else {
                rs = this.db.executeQuery(sql, params);
            }

            list = this.buildList(clazz, fieldNameList, rs);
        } catch (Exception var14) {
            var14.printStackTrace();
        } finally {
            if (!this.beginTransaction) {
                this.db.DBClose();
            }

        }

        return list;
    }

    private Object buildOneObject(Class clazz, List<Property> fieldNameList, ResultSet rs) {
        Object obj = null;

        try {
            obj = clazz.newInstance();
        } catch (Exception var15) {
            var15.printStackTrace();
        }

        for(int i = 0; i < fieldNameList.size(); ++i) {
            Property property = (Property)fieldNameList.get(i);
            String columnName = property.getColumn();
            String propertyName = property.getName();
            String firstPropertyName = propertyName.substring(0, 1).toUpperCase();
            String leftPropertyName = propertyName.substring(1);
            String methodName = "set" + firstPropertyName + leftPropertyName;

            try {
                Class returnType = CDataType.getObjectDataType(property.getFieldType());
                Method method = clazz.getDeclaredMethod(methodName, returnType);
                method.invoke(obj, CDataType.getData(returnType, rs, columnName));
            } catch (Exception var14) {
                var14.printStackTrace();
            }
        }

        return obj;
    }

    private List buildList(Class clazz, List<Property> fieldNameList, ResultSet rs) {
        ArrayList list = new ArrayList();

        try {
            while(rs.next()) {
                Object obj = this.buildOneObject(clazz, fieldNameList, rs);
                list.add(obj);
            }
        } catch (SQLException var6) {
            var6.printStackTrace();
        }

        return list;
    }

    private List<Property> getFieldNameList(String className, String sql) {
        ClassItem classItem = Configuration.getClassItem(className);
        Map<String, Property> columnPropertyMap = classItem.getColumnPropertyMap();
        int startIndex = sql.indexOf("select");
        if (startIndex < 0) {
            startIndex = sql.indexOf("SELECT");
        }

        startIndex += 6;
        int endIndex = sql.indexOf("from");
        if (endIndex < 0) {
            endIndex = sql.indexOf("FROM");
        }

        List<Property> fieldNameList = new ArrayList();
        String fieldNames = sql.substring(startIndex, endIndex);
        boolean isAll = false;
        if (fieldNames != null && fieldNames.contains("*")) {
            isAll = true;
        }

        if (isAll) {
            fieldNameList = classItem.getPropertyList();
            return fieldNameList;
        } else {
            String[] fieldNameArray = fieldNames.split(",");
            if (fieldNameArray != null) {
                for(int i = 0; i < fieldNameArray.length; ++i) {
                    String fieldName = this.parseField(fieldNameArray[i]);
                    if (columnPropertyMap.containsKey(fieldName)) {
                        fieldNameList.add((Property)columnPropertyMap.get(fieldName));
                    }
                }
            }

            return fieldNameList;
        }
    }

    private String parseField(String fieldName) {
        fieldName = fieldName.trim();
        if (fieldName.contains(".")) {
            fieldName = fieldName.substring(fieldName.indexOf(".") + 1);
            fieldName = fieldName.trim();
        }

        return fieldName;
    }

    private ClassItem buildRealTableMeta(Field[] fields, String className, String tableName) {
        ClassItem classItem = Configuration.getClassItem(className);
        if (classItem == null) {
            classItem = new ClassItem();
            classItem.setName(className);
            classItem.setTable(tableName.toLowerCase());
        }

        this.buildRealTableColumn(fields, classItem, className, tableName);
        return classItem;
    }

    private void buildRealTableColumn(Field[] fields, ClassItem classItem, String className, String tableName) {
        ConcurrentHashMap<String, Property> propertyMap = classItem.getPropertyMap();
        if (fields != null && fields.length > 0) {
            for(int i = 0; i < fields.length; ++i) {
                Field field = fields[i];
                if (CDataType.isDatabaseField(field.getType())) {
                    String name = field.getName();
                    String column = field.getName();
                    Property property = (Property)propertyMap.get(name);
                    if (property == null) {
                        property = new Property();
                        property.setName(name);
                        property.setColumn(name);
                        propertyMap.put(name, property);
                    }

                    property.setFieldType(field.getType());
                }
            }
        }

    }

    private Object[] buildInsertSQL(ClassItem classItem, Object obj) {
        Object[] returnObj = new Object[2];
        Class clazz = obj.getClass();
        ConcurrentHashMap<String, Property> propertyMap = classItem.getPropertyMap();
        List<Object> params = new ArrayList();
        StringBuffer sb = new StringBuffer();
        StringBuffer sbValue = new StringBuffer();
        sb.append("insert into ").append(classItem.getTable()).append("(");
        Iterator iter = propertyMap.entrySet().iterator();

        while(true) {
            Property property;
            do {
                if (!iter.hasNext()) {
                    sb.delete(sb.length() - 1, sb.length());
                    sb.append(")values(");
                    sbValue.delete(sbValue.length() - 1, sbValue.length());
                    sb.append(sbValue).append(")");
                    returnObj[0] = sb.toString();
                    returnObj[1] = params.toArray();
                    return returnObj;
                }

                Entry<String, Property> entry = (Entry)iter.next();
                property = (Property)entry.getValue();
            } while(property.isKey() && Constants.KEY_AUTO_INCREMENT.equals(property.getGenerator()));

            sb.append(property.getColumn()).append(",");
            sbValue.append("?,");
            String fieldName = property.getName();
            String firstFieldName = fieldName.substring(0, 1).toUpperCase();
            String leftFieldName = fieldName.substring(1);
            String methodName = "get" + firstFieldName + leftFieldName;

            try {
                Method method = clazz.getDeclaredMethod(methodName);
                Object resultObj = method.invoke(obj);
                params.add(resultObj);
            } catch (Exception var18) {
                var18.printStackTrace();
            }
        }
    }

    private Object[] buildUpdateSQL(ClassItem classItem, Object obj) {
        Object[] returnObj = new Object[2];
        Class clazz = obj.getClass();
        ConcurrentHashMap<String, Property> propertyMap = classItem.getPropertyMap();
        List<Object> params = new ArrayList();
        StringBuffer sb = new StringBuffer();
        sb.append("update ").append(classItem.getTable()).append(" set ");
        Iterator iter = propertyMap.entrySet().iterator();

        String fieldName;
        String methodName;
        while(iter.hasNext()) {
            Entry<String, Property> entry = (Entry)iter.next();
            Property property = (Property)entry.getValue();
            if (!property.isKey()) {
                sb.append(property.getColumn()).append("=?,");
                fieldName = property.getName();
                methodName = fieldName.substring(0, 1).toUpperCase();
                String leftFieldName = fieldName.substring(1);
             methodName = "get" + methodName + leftFieldName;

                try {
                    Method method = clazz.getDeclaredMethod(methodName);
                    Object resultObj = method.invoke(obj);
                    params.add(resultObj);
                } catch (Exception var18) {
                    var18.printStackTrace();
                }
            }
        }

        sb.delete(sb.length() - 1, sb.length());
        	fieldName = classItem.getKeyName();
        String firstFieldName = fieldName.substring(0, 1).toUpperCase();
        fieldName = fieldName.substring(1);
        methodName = "get" + firstFieldName + fieldName;

        try {
            Method method = clazz.getDeclaredMethod(methodName);
            Object resultObj = method.invoke(obj);
            params.add(resultObj);
        } catch (Exception var17) {
            var17.printStackTrace();
        }

        sb.append(" where ").append(classItem.getKeyName()).append("=?");
        returnObj[0] = sb.toString();
        returnObj[1] = params.toArray();
        return returnObj;
    }

    private Object[] buildDeleteSQL(ClassItem classItem, Object obj) {
        Object[] returnObj = new Object[2];
        Class clazz = obj.getClass();
        ConcurrentHashMap<String, Property> propertyMap = classItem.getPropertyMap();
        List<Object> params = new ArrayList();
        StringBuffer sb = new StringBuffer();
        sb.append("delete from ").append(classItem.getTable());
        String fieldName = classItem.getKeyName();
        String firstFieldName = fieldName.substring(0, 1).toUpperCase();
        String leftFieldName = fieldName.substring(1);
        String methodName = "get" + firstFieldName + leftFieldName;

        try {
            Method method = clazz.getDeclaredMethod(methodName);
            Object resultObj = method.invoke(obj);
            params.add(resultObj);
        } catch (Exception var14) {
            var14.printStackTrace();
        }

        sb.append(" where ").append(classItem.getKeyName()).append("=?");
        returnObj[0] = sb.toString();
        returnObj[1] = params.toArray();
        return returnObj;
    }

    public boolean executeUpdate(String sql) {
        return this.beginTransaction ? this.db.executeTransactionUpdate(sql) : this.db.executeUpdate(sql);
    }

    public ResultSet executeQuery(String sql) {
        return this.beginTransaction ? this.db.executeTransactionQuery(sql) : this.db.executeQuery(sql);
    }

    public boolean executeUpdate(String sql, Object[] params) {
        return this.beginTransaction ? this.db.executeTransactionUpdate(sql, params) : this.db.executeUpdate(sql, params);
    }

    public ResultSet executeQuery(String sql, Object[] params) {
        return this.beginTransaction ? this.db.executeTransactionQuery(sql, params) : this.db.executeQuery(sql, params);
    }

    public void beginTransaction() {
        this.beginTransaction = true;
        this.db.openTransactionConnection();
    }

    public void commit() {
        this.db.commit();
        this.beginTransaction = false;
    }

    public void rollback() {
        this.db.rollback();
        this.beginTransaction = false;
    }

    public void close() {
        this.db.DBClose();
    }
}
